package com.heimachefu.module.user.service.impl;

import com.heimachefu.common.CommonUtils;
import com.heimachefu.common.Result;
import com.heimachefu.module.resource.entity.ResourceEntity;
import com.heimachefu.module.resource.service.ResourceService;
import com.heimachefu.module.user.check.UserParam;
import com.heimachefu.module.user.dao.UserRepository;
import com.heimachefu.module.user.entity.UserEntity;
import com.heimachefu.module.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.*;
import java.util.List;

/**
 * @author liuxingdong@heimachefu.com
 * @date 2019/7/19 11:29
 */
@Service
public class UserServiceImpl implements UserDetailsService, UserService{

    private final UserRepository userRepository;

    private final ResourceService resourceService;

    @Autowired
    public UserServiceImpl(UserRepository userRepository, ResourceService resourceService) {
        this.userRepository = userRepository;
        this.resourceService = resourceService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
       return userRepository.findByUsername(username);
    }

    @Override
    public List<ResourceEntity> getAuthResourceListForUser(Long userId) {
        return resourceService.getChildResourceList(userRepository.getAuthResourceForUser(userId));
    }

    @Override
    public Page<UserEntity> list(UserParam userParam) {
        Pageable pageable =  PageRequest.of(userParam.getPageNo(), userParam.getPageSize()); //页码：前端从1开始，jpa从0开始，做个转换
        //通常使用 Specification 的匿名内部类
        Specification<UserParam> specification = new Specification<UserParam>() {
            /**
             * @param *root: 代表查询的实体类.
             * @param query: 可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 还可以
             * 来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象.
             * @param *cb: CriteriaBuilder 对象. 用于创建 Criteria 相关对象的工厂. 当然可以从中获取到 Predicate 对象
             * @return: *Predicate 类型, 代表一个查询条件.
             */
            @Override
            public Predicate toPredicate(Root<UserParam> root,
                                         CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = cb.conjunction();
                if(!StringUtils.isEmpty(userParam.getMobile())){
                    predicate.getExpressions().add((cb.like(root.get("mobile"),userParam.getMobile())));
                }
                if(!StringUtils.isEmpty(userParam.getUsername())){
                    predicate.getExpressions().add(cb.like(root.get("username"),userParam.getUsername()));
                }
               return predicate;
            }
        };
        return userRepository.findAll(specification,pageable);
    }

    @Override
    public Result remove(Long userId) {
        userRepository.deleteById(userId);
        return CommonUtils.success("删除成功",null);
    }
}
